package com.yunkeji.api.user.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;

import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yunkeji.api.auth.service.AuthService;
import com.yunkeji.api.common.service.SysParamService;
import com.yunkeji.api.user.bo.RealAuthBo;
import com.yunkeji.api.user.mapper.ApiAppUserMapper;
import com.yunkeji.api.user.service.AppUserAuthService;
import com.yunkeji.api.user.vo.AuthQuery;
import com.yunkeji.api.user.vo.InvitedParamVo;
import com.yunkeji.common.constant.CacheConstants;
import com.yunkeji.common.constant.SysConfigConsts;
import com.yunkeji.common.enums.app.AppUserOnlineStatus;
import com.yunkeji.common.enums.app.AppUserStatus;
import com.yunkeji.common.enums.app.CheckStatus;
import com.yunkeji.common.enums.app.CheckType;
import com.yunkeji.common.exception.AppServiceException;
import com.yunkeji.common.helper.LoginHelper;
import com.yunkeji.common.msg.PushMessage;
import com.yunkeji.dao.domain.AppUser;
import com.yunkeji.dao.domain.AppUserExt;
import com.yunkeji.dao.domain.UserBanned;
import com.yunkeji.dao.domain.UserCheck;
import com.yunkeji.dao.mapper.AppUserExtMapper;
import com.yunkeji.dao.mapper.UserBannedMapper;
import com.yunkeji.dao.mapper.UserCheckMapper;
import com.yunkeji.utils.IdCardAuthUtils;

import lombok.RequiredArgsConstructor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Date;

@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Service
public class AppUserAuthServiceImpl implements AppUserAuthService {

    private final ApiAppUserMapper appUserMapper;
    private final AppUserExtMapper appUserExtMapper;
    @Autowired @Lazy AuthService authService;
    private final SysParamService sysParamService;
    private final UserCheckMapper userCheckMapper;
    private final UserBannedMapper userBannedMapper;

    @Override
    public String refreshKmsgToken() {
        Long platformId = LoginHelper.getLoginUser().getPlatformId();
        String s = authService.refreshKmsgToken(platformId);
        return s;
    }

    @Lock4j(
            name = CacheConstants.LOCK_CHECK,
            keys = {"#bo.lockId"})
    @Override
    public void realAuth(RealAuthBo bo) {
        if (CheckType.getByCode(bo.getCheckType()).getCode() == CheckType.实名认证.getCode()) {
            realNameAuth(bo);
        } else {
            videoAuth(bo);
        }
    }

    /**
     * 真人认证
     *
     * @author 老张
     */
    private void videoAuth(RealAuthBo bo) {
        if (StrUtil.isEmpty(bo.getResUrl())) {
            throw AppServiceException.paramException("资源异常");
        }
        checkApplyStatus(bo);
        //  提交真人认证被拒绝后必须72小时以后才能再次提交
        UserCheck userCheckReject =
                userCheckMapper.selectOne(
                        Wrappers.lambdaQuery(UserCheck.class)
                                .eq(UserCheck::getStatus, CheckStatus.审核拒绝.getCode())
                                .eq(UserCheck::getCheckType, bo.getCheckType())
                                .eq(UserCheck::getUserId, LoginHelper.getUserId()),false);
        if (userCheckReject != null) {
            Date updateTime = userCheckReject.getUpdateTime();
            long l = DateUtil.betweenMs(updateTime, new Date());
            if (l < 72 * 60 * 60 * 1000) {
                //TODO   @老张 真人认证没有通过72小时后才能再提交，先取消了。后面人上差不多了再开始执行
                //  throw AppServiceException.paramException("您近期被拒绝了提交真人认证,请72小时后再试");
            }
        }
        Integer num =
                Integer.parseInt(sysParamService.selectConfigByKey(SysConfigConsts.真人认证邀请好友数量));
        if (num > 0) {
            Long aLong =
                    appUserMapper.selectCount(
                            Wrappers.lambdaQuery(AppUser.class)
                                    .eq(AppUser::getPid, LoginHelper.getUserId()));
            if (aLong < num) {
                throw AppServiceException.paramException("暂未满足邀请人数,不可提交真人认证");
            }
        }
        UserCheck build =
                UserCheck.builder()
                        .userId(LoginHelper.getUserId())
                        .platformId(LoginHelper.getPlatformId())
                        .checkRes(new CheckType.VideoAuth().setResUrl(bo.getResUrl()).toString())
                        .checkType(CheckType.真人认证.getCode())
                        .build();
        userCheckMapper.insert(build);
    }

    /**
     * 实名认证
     *
     * @author 老张
     */
    private void realNameAuth(RealAuthBo bo) {
        boolean validCard = IdcardUtil.isValidCard(bo.getIdCard());
        if (!validCard) {
            throw AppServiceException.paramException("身份证号码异常");
        }
        if (StrUtil.isEmpty(bo.getRealName())) {
            throw AppServiceException.paramException("姓名异常");
        }
        checkApplyStatus(bo);
        Boolean match = IdCardAuthUtils.isMatch(bo.getRealName(), bo.getIdCard());
        // 不匹配人工审核
        UserCheck build =
                UserCheck.builder()
                        .userId(LoginHelper.getUserId())
                        .platformId(LoginHelper.getPlatformId())
                        .checkRes(
                                new CheckType.RealAuth()
                                        .setResUrl(bo.getResUrl())
                                        .setRealName(bo.getRealName())
                                        .setCardNum(bo.getIdCard())
                                        .toString())
                        .checkType(CheckType.实名认证.getCode())
                        .build();
        if (match) {
            AppUser appUser = appUserMapper.selectById(LoginHelper.getUserId());
            appUser.setCardAuth(CheckStatus.审核通过.getCode());
            AppUserExt appUserExt = appUserExtMapper.selectById(LoginHelper.getUserId());
            appUserExt.setRealName(bo.getRealName());
            appUserExt.setCardNum(bo.getIdCard());
            appUserExtMapper.updateById(appUserExt);
            appUserMapper.updateById(appUser);
            build.setStatus(CheckStatus.审核通过.getCode());
            build.setRemark("系统自动审核");
        }
        userCheckMapper.insert(build);
    }

    private void checkApplyStatus(RealAuthBo bo) {

        UserCheck userCheckPass =
                userCheckMapper.selectOne(
                        Wrappers.lambdaQuery(UserCheck.class)
                                .eq(UserCheck::getStatus, CheckStatus.审核通过.getCode())
                                .eq(UserCheck::getCheckType, bo.getCheckType())
                                .eq(UserCheck::getUserId, LoginHelper.getUserId()));
        if (userCheckPass != null) {
            throw AppServiceException.paramException("您已经通过了申请");
        }
        UserCheck userCheckProcess =
                userCheckMapper.selectOne(
                        Wrappers.lambdaQuery(UserCheck.class)
                                .eq(UserCheck::getStatus, CheckStatus.待审核.getCode())
                                .eq(UserCheck::getCheckType, bo.getCheckType())
                                .eq(UserCheck::getUserId, LoginHelper.getUserId()));
        if (userCheckProcess != null) {
            throw AppServiceException.paramException("您已经提交了申请");
        }
    }

    /** 注销账号 */
    @Override
    public void delAccount() {
        AppUser appUser = appUserMapper.selectById(LoginHelper.getUserId());
        LoginHelper.removeLoginCacheInfo(appUser.getId());
        String activeProfile = SpringUtil.getActiveProfile();
        DateTime dateTime = null;
        if (activeProfile.equalsIgnoreCase("prod")) {
            // 生产环境下7天，其他10秒
            dateTime = DateUtil.offsetDay(new Date(), 7);
        } else {
            dateTime = DateUtil.offsetMinute(new Date(), 10);
        }
        appUserMapper.updateById(
                new AppUser()
                        .setAccountDelDate(dateTime)
                        .setStatus(AppUserStatus.等待删除.getCode())
                        .setId(appUser.getId()));
    }

    @Override
    public void logout() {
        Long userId = LoginHelper.getUserId();
        LoginHelper.removeLoginCacheInfo(LoginHelper.getUserId());
        appUserMapper.updateById(
                new AppUser().setOnlineStatus(AppUserOnlineStatus.离线.getCode()).setId(userId));
    }

    /**
     * 认证查询
     *
     * @return
     */
    @Override
    public AuthQuery authQuery() {
        AppUser appUser = appUserMapper.selectById(LoginHelper.getUserId());
        return AuthQuery.builder()
                .cardAuth(appUser.getCardAuth())
                .videoAuth(appUser.getVideoAuth())
                .build();
    }

    /**
     * 真人认证邀请的参数
     *
     * @return
     */
    @Override
    public InvitedParamVo getInvitedParam() {
        return InvitedParamVo.builder()
                .limitInvitedNum(
                        Integer.parseInt(
                                sysParamService.selectConfigByKey(SysConfigConsts.真人认证邀请好友数量)))
                .invitedNum(
                        appUserMapper.selectCount(
                                Wrappers.lambdaQuery(AppUser.class)
                                        .eq(AppUser::getPid, LoginHelper.getUserId())))
                .build();
    }

    /**
     * 封号 time 分钟
     *
     * @return
     */
    @Override
    public void banUser(AppUser appUser, Integer time, String reason) {

        AppUserExt appUserExt1 = appUserExtMapper.selectById(appUser.getId());
        DateTime dateTime = DateUtil.offsetMinute(new Date(), time);

        UserBanned userBanned = new UserBanned();
        userBanned.setUserId(appUser.getId());
        userBanned.setPhoneNum(appUser.getPhone());
        userBanned.setReason(reason);
        userBanned.setEndTime(dateTime);
        userBanned.setLimitType(0);
        userBanned.setNickName(appUserExt1.getNickName());
        userBanned.setPlatformId(appUser.getPlatformId());
        userBanned.setHeadUrl(appUserExt1.getHeadUrl());
        userBannedMapper.insert(userBanned);

        AppUser newUser = new AppUser();
        newUser.setId(appUser.getId());
        newUser.setStatus(AppUserStatus.封号.getCode());
        newUser.setOnlineStatus(AppUserOnlineStatus.离线.getCode());
        newUser.setLimitDate(dateTime);
        appUserMapper.updateById(newUser);

        LoginHelper.removeLoginCacheInfo(appUser.getId());
    }
}
